package com.amos.base.config;

import com.amos.base.exception.ApplicationException;
import com.amos.base.redis.lock.CacheLock;
import com.amos.base.redis.lock.LockedComplexObject;
import com.amos.base.redis.lock.LockedObject;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 拦截获取注解的方法和参数，在执行注解的方法前面加锁，执行被注解的方法后释放锁
 */
public class CacheLockInterceptor implements InvocationHandler {

    public static int ERROR_COUNT = 0;
    private Object proxied;

    public CacheLockInterceptor(Object proxied) {
        this.proxied = proxied;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        CacheLock cacheLock = method.getAnnotation(CacheLock.class);
        // 方面前面没添加锁 直接pass
        if (null == cacheLock) {
            return method.invoke(proxied,args);
        }
        // 获取方法中参数的注解
        Annotation[][] annotations = method.getParameterAnnotations();
        // 根据获取到的参数注解和参数列表获取加锁的对象
        Object lockedObject = getLockedObject(annotations,args);
        String objectValue = lockedObject.toString();
        // 新建一个锁

        return null;
    }

    private Object getLockedObject(Annotation[][] annotations,Object[] args){
        if (null == args || args.length == 0) {
            throw new ApplicationException("方法参数为空，没有被锁定的对象");
        }
        if (null == annotations || annotations.length == 0) {
            throw new ApplicationException("没有注解的参数");
        }

        // 不支持多个参数加锁，只支持第一个注解为 locakedObject 或者lockedComplexObject的参数
        int index = -1;
        for (int i=0;i<annotations.length;i++){
            for (int j=0;j<annotations[i].length;j++) {
                // 注解为LockedComplexObject对象
                if (annotations[i][j] instanceof LockedComplexObject) {
                    index = i;
                    try{
                        return args[i].getClass().getField(((LockedComplexObject)annotations[i][j]).field());
                    }catch (Exception e){
                        e.printStackTrace();
                        throw new ApplicationException("注解对象中没有该属性："+((LockedComplexObject)annotations[i][j]).field());
                    }
                }

                if (annotations[i][j] instanceof LockedObject){
                    index = i;
                    break;
                }
            }

            if (index != -1) {
                break;
            }
        }

        if (index == -1){
            throw new ApplicationException("请指定被锁定的参数");
        }
        return args[index];
    }
}
